/*
 * 中断和异常处理框架实现
 * 基于xv6的设计，适配riscv-os
 */

#include "trap.h"
#include "riscv_regs.h"
#include "../fs/printf.h"
#include "../mm/kalloc.h"
#include "../mm/vm.h"

// 中断向量表
static interrupt_handler_t interrupt_handlers[MAX_IRQ_NUM];
static exception_handler_t exception_handlers[16];

// 系统时钟计数
uint64 ticks = 0;

// 时钟中断间隔（微秒）
#define TIMER_INTERVAL 1000000

/*
 * 初始化中断系统
 */
void trap_init(void)
{
    printf("Initializing trap system...\n");
    
    // 清空中断向量表
    for (int i = 0; i < MAX_IRQ_NUM; i++) {
        interrupt_handlers[i] = 0;
    }
    
    // 清空异常处理表
    for (int i = 0; i < 16; i++) {
        exception_handlers[i] = 0;
    }
    
    // 注册默认的时钟中断处理函数
    register_interrupt(IRQ_S_TIMER, timer_interrupt);
    
    printf("Trap system initialized.\n");
}

/*
 * 初始化当前hart的中断
 */
void trap_init_hart(void)
{
    // 设置内核中断向量
    w_stvec((uint64)kernelvec);
    
    // 启用时钟中断
    w_sie(r_sie() | SIE_STIE);
    
    // 启用全局中断
    intr_on();
    
    printf("Hart trap initialized.\n");
}

/*
 * 注册中断处理函数
 */
void register_interrupt(int irq, interrupt_handler_t handler)
{
    if (irq >= 0 && irq < MAX_IRQ_NUM) {
        interrupt_handlers[irq] = handler;
        printf("Registered interrupt handler for IRQ %d\n", irq);
    }
}

/*
 * 注册异常处理函数
 */
void register_exception(int cause, exception_handler_t handler)
{
    if (cause >= 0 && cause < 16) {
        exception_handlers[cause] = handler;
        printf("Registered exception handler for cause %d\n", cause);
    }
}

/*
 * 开启特定中断
 */
void enable_interrupt(int irq)
{
    uint64 sie = r_sie();
    switch (irq) {
        case IRQ_S_TIMER:
            sie |= SIE_STIE;
            break;
        case IRQ_S_EXT:
            sie |= SIE_SEIE;
            break;
        case IRQ_S_SOFT:
            sie |= SIE_SSIE;
            break;
    }
    w_sie(sie);
}

/*
 * 关闭特定中断
 */
void disable_interrupt(int irq)
{
    uint64 sie = r_sie();
    switch (irq) {
        case IRQ_S_TIMER:
            sie &= ~SIE_STIE;
            break;
        case IRQ_S_EXT:
            sie &= ~SIE_SEIE;
            break;
        case IRQ_S_SOFT:
            sie &= ~SIE_SSIE;
            break;
    }
    w_sie(sie);
}

/*
 * 内核态中断处理
 */
void kerneltrap(void)
{
    uint64 sepc = r_sepc();
    uint64 sstatus = r_sstatus();
    uint64 scause = r_scause();
    
    // 检查是否来自supervisor模式
    if ((sstatus & SSTATUS_SPP) == 0) {
        printf("kerneltrap: not from supervisor mode\n");
        return;
    }
    
    // 检查中断是否被禁用
    if (intr_get() != 0) {
        printf("kerneltrap: interrupts enabled\n");
        return;
    }
    
    // 处理中断或异常
    if ((scause & 0x8000000000000000L) != 0) {
        // 中断
        devintr();
    } else {
        // 异常
        handle_exception(scause, sepc, r_stval());
    }
    
    // 恢复sepc和sstatus
    w_sepc(sepc);
    w_sstatus(sstatus);
}

/*
 * 用户态中断处理（简化版）
 */
uint64 usertrap(void)
{
    uint64 scause = r_scause();
    
    // 设置内核中断向量
    w_stvec((uint64)kernelvec);
    
    if ((scause & 0x8000000000000000L) != 0) {
        // 中断
        devintr();
    } else {
        // 异常
        handle_exception(scause, r_sepc(), r_stval());
    }
    
    return 0; // 简化返回
}

/*
 * 设备中断处理
 */
int devintr(void)
{
    uint64 scause = r_scause();
    
    if ((scause & 0x8000000000000000L) && (scause & 0xff) == 9) {
        // 外部中断
        printf("External interrupt\n");
        return 1;
    } else if ((scause & 0x8000000000000000L) && (scause & 0xff) == 5) {
        // 时钟中断
        if (interrupt_handlers[IRQ_S_TIMER]) {
            interrupt_handlers[IRQ_S_TIMER]();
        }
        return 2;
    } else if ((scause & 0x8000000000000000L) && (scause & 0xff) == 1) {
        // 软件中断
        printf("Software interrupt\n");
        return 3;
    } else {
        return 0;
    }
}

/*
 * 异常处理
 */
void handle_exception(uint64 cause, uint64 epc, uint64 tval)
{
    printf("Exception: cause=0x%lx, epc=0x%lx, tval=0x%lx\n", cause, epc, tval);
    
    // 调用注册的异常处理函数
    if (cause < 16 && exception_handlers[cause]) {
        exception_handlers[cause](cause, epc, tval);
        return;
    }
    
    // 默认异常处理
    switch (cause) {
        case CAUSE_INSTRUCTION_MISALIGNED:
            printf("Instruction address misaligned\n");
            break;
        case CAUSE_INSTRUCTION_ACCESS_FAULT:
            printf("Instruction access fault\n");
            break;
        case CAUSE_ILLEGAL_INSTRUCTION:
            printf("Illegal instruction\n");
            break;
        case CAUSE_BREAKPOINT:
            printf("Breakpoint\n");
            break;
        case CAUSE_LOAD_MISALIGNED:
            printf("Load address misaligned\n");
            break;
        case CAUSE_LOAD_ACCESS_FAULT:
            printf("Load access fault\n");
            break;
        case CAUSE_STORE_MISALIGNED:
            printf("Store address misaligned\n");
            break;
        case CAUSE_STORE_ACCESS_FAULT:
            printf("Store access fault\n");
            break;
        case CAUSE_USER_ECALL:
            printf("User environment call\n");
            syscall();
            break;
        case CAUSE_SUPERVISOR_ECALL:
            printf("Supervisor environment call\n");
            break;
        case CAUSE_INSTRUCTION_PAGE_FAULT:
            printf("Instruction page fault\n");
            break;
        case CAUSE_LOAD_PAGE_FAULT:
            printf("Load page fault\n");
            break;
        case CAUSE_STORE_PAGE_FAULT:
            printf("Store page fault\n");
            break;
        default:
            printf("Unknown exception: %ld\n", cause);
            break;
    }
    
    // 对于严重异常，停止系统
    printf("System halted due to exception\n");
    while (1) {
        asm volatile("wfi"); // 等待中断
    }
}

/*
 * 时钟中断处理
 */
void timer_interrupt(void)
{
    // 增加系统时钟计数
    ticks++;
    
    // 设置下次时钟中断
    set_next_timer();
    
    // 每100个时钟周期打印一次（可选）
    if (ticks % 100 == 0) {
        printf("Timer tick: %ld\n", ticks);
    }
}

/*
 * 设置下次时钟中断
 */
void set_next_timer(void)
{
    // 简化版本，暂时不设置时钟中断
    // sbi_set_timer(r_time() + TIMER_INTERVAL);
}

/*
 * 初始化时钟
 */
void timer_init(void)
{
    printf("Initializing timer...\n");
    
    // 简化版本，暂时不设置时钟中断
    // set_next_timer();
    
    printf("Timer initialized.\n");
}

/*
 * 系统调用处理（简化版）
 */
void syscall(void)
{
    printf("System call not implemented yet\n");
}

// panic函数在printf.c中已定义